package cn.migu.music.hangupsms.common.aop;

import cn.migu.music.common.redis.IRedisClient;
import cn.migu.music.common.utils.LogUtils;
import cn.migu.music.hangupsms.common.config.HangUpSmsConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @version 1.0 created by duanhao@migu.cn on 2022/3/4 6:42 下午
 */
@Component
@Aspect
@Slf4j
public class RateLimitAspect {

    @Autowired
    private HangUpSmsConfig hangUpSmsConfig;
    @Autowired
    private IRedisClient    redisClient;

    @Pointcut("@annotation(cn.migu.music.hangupsms.common.aop.RateLimit)")
    public void serviceLimit() {
        // 这是个注解切面
    }

    @Around("serviceLimit()")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object obj = null;
        // 返回被织入增加处理目标对象
        String argsStr = JSON.toJSONString(joinPoint.getArgs()[0]);
        JSONObject argsJsonObject = JSON.parseObject(argsStr);
        String provinceId = argsJsonObject.getString("provinceId");
        int limitNum = Integer.parseInt(hangUpSmsConfig.getLimitCountMap().get(provinceId)); // 获取注解每秒加入桶中的token
        LocalDateTime now = LocalDateTime.now();
        String redisKey = "RATELIMITER_" + now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + "_" + provinceId;
        String ratelimitNum = redisClient.get(redisKey);
        int currentCount = Integer.parseInt(StringUtils.defaultIfEmpty(ratelimitNum, "0"));
        try {
            if (currentCount < limitNum) {
                // 执行方法
                Long num = redisClient.incr(redisKey);
                if (num == 1) {
                    redisClient.expire(redisKey, hangUpSmsConfig.getRatelimitInterval());
                }
                obj = joinPoint.proceed();

            } else {
                // 拒绝了请求（服务降级）
                LogUtils.info(log, "限流了,当前时间%s", now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")));
            }
        } catch (Throwable throwable) {
            LogUtils.info(throwable, log, "限流器异常");
        }
        return obj;
    }

}
